//
// Maths.cpp for  in /home/goldbe_y//tek3/Projets/Maths/302graphe
// 
// Made by yoni goldberg
// Login   <goldbe_y@epitech.net>
// 
// Started on  Mon Sep 24 14:39:22 2012 yoni goldberg
// Last update Fri Oct 12 15:43:09 2012 yoni goldberg
//

#include "Maths.hpp"

Maths::Maths(const std::string &str)
{
  Parse	tmp(str);

  _str = "";
  _sommets = 0;
  _tab = tmp.get_from_file();
  _line = tmp.getLine();
  nombre_sommet();
  get_first_matrix();
  get_second_matrix();
}

Maths::~Maths()
{
  delete_matrix(_matrix);
  delete_matrix(_mat2);
}

void		Maths::init_matrix(int ***matrix)
{
  *matrix = new int*[_sommets];
  for (int i = 0; i < _sommets; i++)
    {
      (*matrix)[i] = new int[_sommets];
      for (int j = 0; j < _sommets; j++)
      	(*matrix)[i][j] = 0;
    }
}

void		Maths::delete_matrix(int **matrix)
{
  for (int i = 0; i < _sommets; i++)
    delete matrix[i];
  delete matrix;
}

void		Maths::init_diag(int ***matrix, int init)
{
  for (int i = 0; i < _sommets; i++)
    (*matrix)[i][i] = init;
}

int	**Maths::get_first_matrix()
{
  init_matrix(&_matrix);
  for (int i = 0; i < _line; i++)
    _matrix[_tab[i][0] - 97][_tab[i][2] - 97] += 1;
  return _matrix;
}

int	**Maths::get_second_matrix()
{
  init_matrix(&_mat2);
  mult_matrix();
  return _mat2;
}

int	**Maths::get_third_matrix()
{
  _mat3 = _matrix;
  init_diag(&_mat3, 1);
  
  for (int k = 0; k < _sommets; k++)
    for (int i = 0; i < _sommets; i++)
      for (int j = 0; j < _sommets; j++)
	if (_mat3[i][k] >= 1 && _mat3[k][j] >= 1)
	  _mat3[i][j] = 1;
  _matrix = get_first_matrix();
  return _mat3;
}

int	**Maths::get_forth_matrix()
{
  _mat4 = _matrix;
  init_diag(&_mat4, 0);

  for (int line = 0; line < _sommets; line++)
    for (int column = 0; column < _sommets; column++)
      if (_mat4[line][column] == 2)
	_mat4[line][column] = 1;

  for (int line = 0; line < _sommets; line++)
    for (int column = 0; column < _sommets; column++)
      if (_mat4[line][column] == 0 && line != column)
	_mat4[line][column] = 42;

  for (int k = 0; k < _sommets; k++)
    for (int i = 0; i < _sommets; i++)
      for (int j = 0; j < _sommets; j++)
	_mat4[i][j] = min(_mat4[i][j], (_mat4[i][k] + _mat4[k][j]));
  _matrix = get_first_matrix();
  return _mat4;
}

int	Maths::min(int a, int b)
{
  int	result = b;

  if (a < b)
    result = a;
  return result;
}

int	Maths::get_line()
{
  return _line;
}

int	Maths::get_sommets()
{
  return _sommets;
}

std::vector<std::string>	Maths::get_tab()
{
  return _tab;
}

int		Maths::calc(int line, int column)
{
  int		result = 0;
  
  for (int i = 0; i < _sommets; i++)
    result += _matrix[line][i] * _matrix[i][column];
  return result;
}
void		Maths::mult_matrix()
{
  for (int line = 0; line < _sommets; line++)
    for (int column = 0; column < _sommets; column++)
      _mat2[line][column] = calc(line, column);
}

void		Maths::aff_matrix(int **matrix)
{
  for (int line = 0; line < _sommets; line++)
    {
      for (int column = 0; column < _sommets; column++)
	if (matrix[line][column] >= 42)
	  std::cout << "x ";
	else
	  std::cout << matrix[line][column] << " ";
      std::cout << std::endl;
    }
  std::cout << std::endl;
}

void	Maths::aff_tab(std::vector<std::string> tab)
{
  for (int i = 0; i < tab.size(); i++)
    std::cout << tab[i] << std::endl;
}

void	Maths::check(char c)
{
  int	i = 0;

  if (_str.size() == 0)
    _str += c;
  while (_str[i] && _str[i] != c){i++;};
  if (i >= _str.size())
    _str += c;
}

void	Maths::nombre_sommet()
{

  for (int i = 0; i < _line; i++)
    {
      check(_tab[i][0]);
      check(_tab[i][2]);
    }
  _sommets = _str.size();
}
